<template>
  <!-- 表单部分 -->
  <el-form :inline="true" :model="queryDto">
    <el-form-item label="角色名称">
      <el-input
        v-model="queryDto.roleName"
        placeholder="请输入角色名称"
        clearable
      />
    </el-form-item>

    <el-form-item>
      <el-button type="primary" @click="onSubmit">查询</el-button>
      <el-button type="info" @click="onSubmit">重置</el-button>
      <el-button type="success" @click="addShow">添加</el-button>
    </el-form-item>
  </el-form>
  <!-- 表格部分 -->
  <el-table :data="tableData" style="width: 100%" fit highlight-current-row>
    <el-table-column fixed prop="roleName" label="角色名称" width="250" />
    <el-table-column prop="roleCode" label="角色Code" width="220" />
    <el-table-column prop="createTime" label="创建时间" width="220" />
    <el-table-column prop="operate" label="操作" #default="scope">
      <el-button type="primary" size="small" @click="editShow(scope.row)">
        修改
      </el-button>
      <el-button type="danger" size="small" @click="deleteById(scope.row)">
        删除
      </el-button>
      <el-button type="warning" size="small" @click="showAssignMenu(scope.row)">
        分配菜单
      </el-button>
    </el-table-column>
  </el-table>

  <el-pagination
    v-model:current-page="pageParamsForm.page"
    v-model:page-size="pageParamsForm.limit"
    :page-sizes="[10, 20, 50, 100, 300, 400]"
    :background="background"
    layout="sizes, pager"
    :total="totle"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
  />

  <!-- 添加角色表单对话框 -->
  <el-dialog
    v-model="dialogVisible"
    :title="addOrUpdata ? '修改角色' : '添加角色'"
    width="30%"
    center
    @closed="dialogClose()"
  >
    <el-form label-width="120px">
      <el-form-item label="角色名称">
        <el-input v-model="roleMessage.roleName" />
      </el-form-item>
      <el-form-item label="角色Code">
        <el-input v-model="roleMessage.roleCode" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitRoleMessage">提交</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </el-form-item>
    </el-form>
  </el-dialog>

  <!-- 分配菜单的对话框 
    tree组件添加ref属性，后期方便进行tree组件对象的获取
  -->
  <el-dialog v-model="dialogMenuVisible" title="分配菜单" width="40%">
    <el-form label-width="80px">
      <el-tree
        :data="sysMenuTreeList"
        ref="tree"
        show-checkbox
        default-expand-all
        :check-on-click-node="true"
        node-key="id"
        :props="defaultProps"
      />
      <el-form-item>
        <el-button type="primary" @click="doAssign">提交</el-button>
        <el-button @click="dialogMenuVisible = false">取消</el-button>
      </el-form-item>
    </el-form>
  </el-dialog>
</template>

<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'
import {
  GetSysRoleListByPage,
  SaveSysRole,
  UpdateSysRole,
  DeleteSysRoleById,
  GetSysRoleMenuIds,
  DoAssignMenuIdToSysRole,
} from '@/api/sysRole'
import { ElMessage, ElMessageBox } from 'element-plus'

let tableData = ref([])
let totle = ref(0)
const pageParamsForm = reactive({
  page: 1, // 页码
  limit: 10, // 每页记录数
})
const queryDto = reactive({
  roleName: '',
})

const background = ref(true)

const handleSizeChange = (val: number) => {
  pageParamsForm.limit = val
  fetchData()
}
const handleCurrentChange = (val: number) => {
  pageParamsForm.page = val
  fetchData()
}

const onSubmit = () => {
  fetchData()
}
onMounted(() => {
  fetchData()
})

const fetchData = async () => {
  const res = await GetSysRoleListByPage(
    pageParamsForm.page,
    pageParamsForm.limit,
    queryDto
  )
  const { data, code, message } = res
  tableData.value = data.list
  totle.value = Math.ceil(data.total / pageParamsForm.limit)
}

// 控制对话是否展示的变量
const dialogVisible = ref(false)
const addOrUpdata = ref(false)
//进入添加
const addShow = () => {
  dialogVisible.value = true
  addOrUpdata.value = false
}

//表单数据模型
const roleMessage = ref({
  id: 0,
  roleCode: '',
  roleName: '',
})
// 添加角色
const submitRoleMessage = async () => {
  if (addOrUpdata.value === true) {
    // 修改角色
    const res = await UpdateSysRole(roleMessage.value)
  } else {
    // 添加角色
    const res = await SaveSysRole(roleMessage.value)
  }
  ElMessage({
    message: `请求成功`,
    type: 'success',
  })
  fetchData()
  dialogVisible.value = false
}

const dialogClose = () => {
  // 清除对话框数据
  roleMessage.value = {
    id: 0,
    roleCode: '',
    roleName: '',
  }
}

// 修改按钮点击事件处理函数
const editShow = row => {
  // 回显数据
  roleMessage.value = row
  // 打开对话框
  dialogVisible.value = true
  addOrUpdata.value = true
}

const deleteById = async row => {
  await ElMessageBox.confirm('此操作将永久删除该记录, 是否继续?', 'Warning', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
  await DeleteSysRoleById(row.id)
  ElMessage.success({
    message: '删除成功',
    type: 'success',
  })
  fetchData()
}

const defaultProps = {
  children: 'children',
  label: 'title',
}
const dialogMenuVisible = ref(false)
const sysMenuTreeList = ref([])
// 树对象变量
const tree = ref()
// 默认选中的菜单数据集合
let roleId = ref()

const showAssignMenu = async row => {
  dialogMenuVisible.value = true
  roleId = row.id
  const { data } = await GetSysRoleMenuIds(row.id) // 请求后端地址获取所有的菜单数据，以及当前角色所对应的菜单数据
  sysMenuTreeList.value = data.sysMenuList
  tree.value.setCheckedKeys(data.roleMenuIds) // 进行数据回显
}

const doAssign = async () => {
  // 获取选中的节点
  const checkedNodes = tree.value.getCheckedNodes()
  // 获取选中的节点
  const checkedNodesIds = checkedNodes.map(node => {
    return {
      id: node.id,
      isHalf: 0,
    }
  })
  // 获取半选中的节点数据，当一个节点的子节点被部分选中时，该节点会呈现出半选中的状态
  const halfCheckedNodes = tree.value.getHalfCheckedNodes()
  const halfCheckedNodesIds = halfCheckedNodes.map(node => {
    // 获取半选中节点的id
    return {
      id: node.id,
      isHalf: 1,
    }
  })
  // 将选中的节点id和半选中的节点的id进行合并
  const menuIds = [...checkedNodesIds, ...halfCheckedNodesIds]
  console.log(menuIds)

  // 构建请求数据
  const assignMenuDto = {
    roleId: roleId,
    menuIdList: menuIds,
  }

  // 发送请求
  await DoAssignMenuIdToSysRole(assignMenuDto)

  ElMessage.success('操作成功')
  // 关闭对话框
  dialogMenuVisible.value = false
}
</script>

<style></style>
